/**
 * @file resource.c
 * @brief Resource Interface
 *
 * @version Fixed
 * @author yemit
 * @date 2012-09-17
 */
#include <stdint.h>
#include <sys/ioctl.h>
#include <string.h>
#include "voice_file.h"
#include "module.h"
#include "flash.h"
#include "dac.h"
#include "unistd.h"
#include "config.h"

static part_t * voice_part = NULL;
static voice_file_t voice_files[CONFIG_VOICE_FILE_MAXINUM];
static uint32_t g_file_count = 0;
static uint32_t g_voice_vol = 0;

int voice_part_init(void)
{
    int count = 0;
    uint32_t offset = 256;
    
    g_file_count = 0;
    
    if ((voice_part = get_part_by_name("voice_file", NULL)) == NULL)
        return -1;
    if (!verify_firmware2(voice_part))
        return -2;

    memset(voice_files, offset, sizeof(voice_files));
    part_read(voice_part, 256, &count, sizeof(count));
    offset += sizeof(count);
    g_file_count = count;

    while(1) {
        if(g_file_count >= CONFIG_VOICE_FILE_MAXINUM) {
            return -3;
        }
        
        part_read(voice_part, offset, \
            voice_files + (g_file_count - count), sizeof(voice_file_t));
        offset += sizeof(voice_file_t);
        voice_files[g_file_count - count].offset += \
            sizeof(count) + sizeof(voice_file_t) * count + 256;
        
        count --;
        if(count == 0)
            break;
    }
   
    return 0;
}

static int voice_file_open(char *name)
{
    uint32_t file_id = 0;
    
    while(1) {
        if(strcmp(name, voice_files[file_id].name) == 0)
            break;
        
        file_id ++;
        if(file_id >= g_file_count)
            return -1;
    }
    
    voice_files[file_id].fptr = 0;
    
    return file_id;
}

static int voice_file_read(int id, uint8_t *buf, size_t size)
{
    voice_file_t *fp;
    uint32_t free_space;
    int ret = 0;
    
    if ((id < 0) || (id >= g_file_count)) return -EINVAL;
    
    fp = voice_files + id;
    
    if (fp->fptr >= fp->fsize) return 0;
    free_space = fp->fsize - fp->fptr;
    if (size > free_space) size = free_space;
    if (size == 0) return 0;

    ret = part_read(voice_part, fp->offset + fp->fptr, buf, size);
    fp->fptr += size;
        
    return ret;
}

int voice_ctrl_volume(uint32_t vol)
{
    if(vol > 3)
        return VOICE_ERR_PARAM;
    g_voice_vol = vol;
    
    return 0;
}

uint8_t dac_file_data[256];
uint8_t dac_data[129];
int voice_file_play(char * pszFile)
{
    int fd, ret;
    uint32_t fsize = 0, dlen;
    dac_info_t param;
    
    if(pszFile == NULL)
        return VOICE_ERR_PARAM;
    
    fd = voice_file_open(pszFile);
    if(fd < 0)
        return VOICE_ERR_OPEN_FILE;
    
    fsize = voice_files[fd].fsize;

    if(fsize <= 0) {
        return VOICE_ERR_FILE_SIZE;
    }

    if(voice_files[fd].bitsPerSample != 8) {
        return VOICE_ERR_FILE_TYPE;
    }
    
    param.baud = voice_files[fd].samplesPerSec;
    param.blow_up = g_voice_vol;
    param.mode = 0;
    if(dac_init(&param) < 0) {
        return VOICE_ERR_OPEN_DEV;
    }

    while(fsize) {
        dlen = fsize > 256 ? 256 : fsize;
        ret = voice_file_read(fd, dac_file_data, dlen);
        if(ret <= 0){
            return ret;
        }
        fsize -= ret;
        dac_write(dac_file_data, dlen);
    }
    ret = 0;
    
    return ret;
}

